#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1000 + 10;
const int MAX_COLORS = 1000 * 1000 + 10;

// 全局变量，符合你的风格
int n;
long long ans;
int mp[MAXN][MAXN];                 // 存储最终画布
int border[MAX_COLORS][4];          // border[c] = {min_r, min_c, max_r, max_c}
int pre[MAXN][MAXN];                // 二维差分数组
int sum[MAXN][MAXN];                // 二维前缀和数组，存储每个格子被覆盖次数
bool is_not_first[MAX_COLORS];      // 标记某个颜色是否“一定不是第一个”

int main() 
{
    #ifdef LOCAL
        freopen("data.in", "r", stdin);
        freopen("data.out", "w", stdout);
        auto start_time = chrono::high_resolution_clock::now();
    #endif
    
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    
    // ================ 你的代码从这里开始 ================
    
    cin >> n;

    // 步骤1: 找到每个颜色可见区域的边界框 (Bounding Box)
    for (int i = 1; i <= n * n; i++) {
        border[i][0] = border[i][1] = n + 1; // min_r, min_c 初始化为一个较大的值
        border[i][2] = border[i][3] = 0;     // max_r, max_c 初始化为一个较小的值
    }

    int visible_color_count = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> mp[i][j];
            int color = mp[i][j];
            if (color == 0) continue;

            // 如果是第一次见到这个颜色，计数器+1
            if (border[color][0] == n + 1) {
                visible_color_count++;
            }
            // 更新边界
            border[color][0] = min(border[color][0], i); // min_r
            border[color][1] = min(border[color][1], j); // min_c
            border[color][2] = max(border[color][2], i); // max_r
            border[color][3] = max(border[color][3], j); // max_c
        }
    }

    // 步骤2: 利用二维差分，为每个边界框区域计数
    for (int i = 1; i <= n * n; i++) {
        if (border[i][0] <= n) { // 如果这个颜色出现过
            int r1 = border[i][0], c1 = border[i][1];
            int r2 = border[i][2], c2 = border[i][3];
            pre[r1][c1]++;
            pre[r2 + 1][c2 + 1]++;
            pre[r1][c2 + 1]--;
            pre[r2 + 1][c1]--;
        }
    }

    // 步骤3: 计算二维前缀和，得到每个格子的覆盖次数
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + pre[i][j];
        }
    }

    // 步骤4: 找出“一定不是第一个”的颜色
    long long not_first_count = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            int color = mp[i][j];
            // 如果一个格子最终是color，但它被超过1个边界框覆盖
            // 说明color盖在了别的颜色上，它就“不是第一个”
            if (color != 0 && sum[i][j] > 1) {
                if (!is_not_first[color]) {
                    is_not_first[color] = true;
                    not_first_count++;
                }
            }
        }
    }
    
    // 步骤5: 处理特殊情况
    // 如果只看到一种颜色，那它一定是最后一个画的，所以它也不是第一个
    // (n=1是例外，只有一种颜色，它既是第一个也是最后一个)
    if (n > 1 && visible_color_count == 1) {
        // 找到这个唯一的颜色
        for (int i = 1; i <= n * n; ++i) {
            if (border[i][0] <= n) { // 找到这个颜色
                if (!is_not_first[i]) { // 如果它还没被标记
                    // 因为sum值此时都为1,所以它不会在上面的循环被标记
                    not_first_count++;
                }
                break;
            }
        }
    }

    // 步骤6: 计算最终答案
    ans = (long long)n * n - not_first_count;
    cout << ans << endl;

    // ================ 你的代码到这里结束 ================
    
    #ifdef LOCAL
        auto end_time = chrono::high_resolution_clock::now();
        auto duration = chrono::duration_cast<chrono::milliseconds>(end_time - start_time);
        cerr << "Time cost: " << duration.count() << " ms" << endl;
    #endif
    
    return 0;
}